#include <cstdlib>
#include <iostream>
#include <fstream>
#include "TFloat.h"
#include <math.h>


using namespace std;


TFloat heron(TFloat u, TFloat v, TFloat w)
{
	TFloat s = (u + v + w) / 2;
	return (s * (s - u) * (s - v) * (s - w)).squareRoot();
}


TFloat diferenciasFaciales(TFloat u, TFloat v, TFloat w)
{
	return ((u + v + w) * (v - w + u) * (w - u + v) * (u - v + w)).squareRoot() / 4;
}


TFloat diferenciasFacialesBien(TFloat u, TFloat v, TFloat w)
{
	u.printDebug(cout);
	cout << endl;
	(v - u).printDebug(cout);
	cout << endl;
	(u - v).printDebug(cout);

	system("PAUSE");

	return ((u + v + w) * (v + u - w) * (w + v - u) * (u + w - v)).squareRoot() / 4;
}


TFloat diferencia(TFloat a, TFloat b, TFloat c)
{
	return ((a > c)? a : c) - b + ((a > c)? c : a);
}


TFloat diferenciasFacialesRevisado(TFloat u, TFloat v, TFloat w)
{
	return ((u + v + w) * diferencia(v, w, u) * diferencia(w, u, v) * diferencia(u, v, w)).squareRoot() / 4;
}

struct Heron 
{
	TFloat operator()(double u, double v, double w)
	{
		return heron(u, v, w);
	}
};

struct DiferenciasFaciales 
{
	TFloat operator()(double u, double v, double w)
	{
		return diferenciasFaciales(u, v, w);
	}
};

struct DiferenciasFacialesBien
{
	TFloat operator()(double u, double v, double w)
	{
		return diferenciasFacialesBien(u, v, w);
	}
};

struct DiferenciasFacialesRevisado 
{
	TFloat operator()(double u, double v, double w)
	{
		return diferenciasFacialesRevisado(u, v, w);
	}
};

template<typename FT> void test1(FT f, ofstream& out)
{
	for (int i = 0; i < 2000; i++)
	{
		double h = 1.0+i*10.0;
		double areaT = f( h, 1, sqrt(h*h+1) ).value();
			
		double area = h/2;

		double dif = ((area > areaT)? (area-areaT) : (areaT - area));

		out << area << "	" << areaT <<  "	" << dif << "	" << dif/area << endl;
	}
}

template<typename FT> void test2(FT f, ofstream& out)
{
	for (int i = 0; i < 1000; i++)
	{
		double h = 1;//+i*10000;
		
		double base = 1+i*0.1;
		
		double lado = ( sqrt( (base/2)*(base/2) + 1 ) ); 

		double areaT = f( base, lado, lado ).value();
			
		double area = base/2;

		double dif = ((area > areaT)? (area-areaT) : (areaT - area));

		out << area << "	" << areaT <<  "	" << dif << "	" << dif/area << endl;
	}
}

template<typename FT> void testEqui(FT f, ofstream& out)
{
	for (int i = 0; i < 5000; i++)
	{
		double base = 1+i*10;
		
		double h = base*(sqrt(3)/2);

		double areaT = f( base, base, base ).value();
			
		double area = base*h/2;

		double dif = ((area > areaT)? (area-areaT) : (areaT - area));

		out << area << "	" << areaT <<  "	" << dif << "	" << dif/area << "	" << base << endl;
	}
}


template<typename FT> void testDecreciente(FT f, ofstream& out)
{
	for (int i = 1; i < 4000; i++)
	{
		double h = 10.0/(i*100);
		double areaT = f( h, 1, sqrt(h*h+1) ).value();

		double area = h/2;

		double dif = ((area > areaT)? (area-areaT) : (areaT - area));

		out << area << "	" << areaT <<  "	" << dif << "	" << dif/area << endl;
	}
}



int main(int argc, char *argv[])
{
	ofstream o("results.txt");

	TFloat::defaultTSize = 10;

	double u = 50;
	double v = 1;
	double w = sqrt(u*u + v*v);
	/*heron(u, v, w).printDebug(cout);
	cout << endl;
	diferenciasFaciales(u, v, w).printDebug(cout);
	cout << endl;
	diferenciasFacialesRevisado(u, v, w).printDebug(cout);
	cout << endl;*/
	//( x * x + y ).printDebug(cout);
	//TFloat(3, 10).printDebug(cout);
	//a.printDebug(cout);
	
	testEqui(Heron(), o);

    system("PAUSE");
    return EXIT_SUCCESS;
}
